﻿using System;
using MemoryPack;

namespace Hsenl {
    // 该复合节点和 ParallelNode 节点的唯一区别在于, 前者始终都会返回 continue, 而该节点只要有一个 succ, 则最终就会返回 succ
    [MemoryPackable]
    public partial class ParalleSelectorNode<TManager, TNode> : CompositeNode<TManager, TNode>
        where TManager : class, IBehaviorTree
        where TNode : class, INode {
        protected new void SetNodeStatus(INode node, NodeStatus status) {
            throw new NotImplementedException();
        }

        protected sealed override bool OnNodeEvaluate() {
            return this.children.Count != 0;
        }

        protected sealed override NodeStatus OnNodeTick() {
            var pos = 0;
            var succ = false;
            CONTINUE:
            if (pos == this.children.Count) {
                return succ ? NodeStatus.Success : NodeStatus.Failure;
            }

            var child = this.children[pos];

            var status = child.EvaluateNode() ? child.TickNode() : NodeStatus.Continue;
            base.SetNodeStatus(child, status);
            if (status == NodeStatus.Running) {
                child.Run();
            }

            switch (status) {
                case NodeStatus.Success:
                    succ = true;
                    break;

                case NodeStatus.Failure:
                case NodeStatus.Continue:
                case NodeStatus.Running:
                    break;

                case NodeStatus.Break:
                    return NodeStatus.Continue;

                case NodeStatus.Return:
                    return NodeStatus.Return;

                default:
                    throw new ArgumentOutOfRangeException($"OnNodeTick can't return {status}");
            }

            pos++;

            goto CONTINUE;
        }
    }

    [MemoryPackable]
    public partial class ParalleSelectorNode : ParalleSelectorNode<IBehaviorTree, INode> { }
}